/**
 * ajax 请求
 * Created by Administrator on 2017-08-11.
 */
import axios from 'axios'
import DateUtil from '@/framework/utils/date-util'
import TokenManager from '@/framework/manager/token-manager'
import AjaxCache from '@/framework/cache/ajaxcache'
import AuthEncrypt from '@/framework/utils/auth-encrypt'

const globalVal = globalThis as any;

const METHOD_GET = 'GET'
const METHOD_POST = 'POST'
const METHOD_PUT = 'PUT'
const METHOD_DELETE = 'DELETE'


const lockMap:any = {}

/**
 * 错误提示
 * @type {Function}
 */
function showError(message:string):void{
  ( globalVal.error || globalVal.toast || globalVal.alert)(message)
}

/**
 * 是否为数组
 */
function isArray (v:any):boolean {
  return toString.apply(v) === '[object Array]'
}

/**
 * 编码请求参数
 * @param val
 * @param pctEncodeSpaces
 * @returns {string}
 */
function encodeUriQuery(val:string, pctEncodeSpaces?:boolean) :string{
  return encodeURIComponent(val)
    .replace(/%40/gi, '@')
    .replace(/%3A/gi, ':')
    .replace(/%24/g, '$')
    .replace(/%2C/gi, ',')
    .replace(/%20/g, (pctEncodeSpaces ? '%20' : '+'))
    .replace(/'/g, '%27')
}

/**
 * 请求数据格式化
 * @param {Object} urlOld
 * @param {Object} paramData
 * @param {Object} method
 */
function httpUrlFormat(urlOld:string, paramData:any, method:string) :string{
  if (paramData) {
    const urlArray:string[] = []

    paramData = isArray(paramData) ? (paramData.length > 0 ? paramData[0] : []) : paramData
    for (const key in paramData) {
      const value = paramData[key]
      if (isArray(value)) {
        if (method.toUpperCase() === 'GET' || method.toUpperCase() === 'DELETE') {
          const arrayValueCell:string[] = []
          for (const keyCell in value) {
            const valueCell = value[keyCell]
            arrayValueCell.push(key + '=' + encodeUriQuery(valueCell))
          }
          if (arrayValueCell.length > 0) {
            const text = arrayValueCell.join('&')
            urlArray.push(text)
          }
        }
      } else {
        if (urlOld.indexOf(':' + key, value) !== -1) {
          urlOld = urlOld.replace(':' + key, encodeUriQuery(value))
        } else {
          if (method.toUpperCase() === 'GET' || method.toUpperCase() === 'DELETE') {
            urlArray.push(key + '=' + encodeUriQuery(value))
          }
        }
      }
    }

    urlArray.sort(function (a, b) {
      return a.localeCompare(b)
    })
    urlOld = encodeURI(urlOld) + (urlArray.length > 0 ? ('?' + urlArray.join('&')) : '')
  } else {
    urlOld = encodeURI(urlOld)
  }
  return (urlOld)
}

/**
 * 授权头
 * @param {Object} method
 * @param {Object} url
 * @param {Object} token
 */
function generateAuthorization(method:string, url:string, token:string):string{
	return AuthEncrypt.getMac(method, url, token);
}

/**
 * 参数重组
 * @param args
 */
function rebuild(args:any):any{
  let config:any = {};
  if(args.length === 1){
    if (typeof args[0] === 'string') {
      config.url = args[0]
    }
    else{
      config = args[0]
    }
  } else if (args.length === 2) {
    config = args[1] ? args[1] : {}
    config.url = args[0]
  }
  else if(args.length === 3) {
    config = args[2] ? args[2] : {}
    config.url = args[0]
    if(args[1] !== null){
      config.data = args[1]
    }
  }
  return config
}

const Http = {
  get: function (...args:any[]) {
    const config = rebuild(args)
    config.method = METHOD_GET
    return Http.execute(config)
  },
  post: function (...args:any[]) {
    const config = rebuild(args)
    config.method = METHOD_POST
    return Http.execute(config)
  },
  put: function (...args:any[]) {
    const config = rebuild(args)
    config.method = METHOD_PUT
    return Http.execute(config)
  },
  delete: function (...args:any[]) {
    const config = rebuild(args)
    config.method = METHOD_DELETE
    return Http.execute(config)
  },

  execute: function (config:any) {
    // 使用Promise 处理成功
    if (config.success == null) {
      return new Promise(function (resolve, reject) {
        config.success = function (res:any) {
          resolve(res)
        }
        if(config.customReject){
          config.reject = function(err:any) {
            reject(err)
          }
        }
        else{
          config.commonReject = function(err:any){
            reject(err)
          }
        }
        Http.doExecute(config)
      })
    } else {
      return new Promise((resolve) => {
        resolve({})
        Http.doExecute(config)
      })

    }
  },
  doExecute: function (config:any) {

    config.method = (config.method || config.type || METHOD_GET).toUpperCase()

    // 设置头部
    config.headers = config.header || config.headers || {}
    // 普通表单方式提交
    if(config.form && config.method === METHOD_POST){
      config.headers['Content-Type'] = config.headers['Content-Type'] || 'application/x-www-form-urlencoded'
    }
    else{
      config.headers['Content-Type'] = config.headers['Content-Type'] || 'application/json'
    }
    /**
     * 设置平台信息
     */


    config.headers['platform'] = 'app'
    config.headers['x-app'] = 'crawler'

    Http.combine(config)
    const lockKey = config.method + '#' + config.url + '#' + JSON.stringify(config.data||{});



    //非GET 对请求加锁处理
    if(config.method != METHOD_GET){
      if(lockMap[lockKey]){
        console.log("重复请求：" + lockKey, lockMap);
        return ;
      }
      lockMap[lockKey] = true
    }

    // 匿名访问
    if(config.anonymous){
      console.log('匿名访问：' + config.url);
    }

    if(!config.url.endsWith('login')){
    // 配置 DEBUG userId 方便调试
      if(globalVal.DEBUG_USERID){
          config.headers['Authorization'] = "DEBUG userId=" + globalVal.DEBUG_USERID;
      }
      else{
        // 设置授权头部
        const token = TokenManager.get();
        config.headers['Authorization'] = generateAuthorization(config.method, config.baseURL + decodeURIComponent(config.url), token)
      }
    }



    // 成功回调
    const successCallback = config.success || function () {
      console.log('TODO')
    }

    // 失败回调
    const errorCallback = config.fail || config.error || function (response:any) {
      if (config.ignore) {
        return
      }
      if (response && response.message) {
        showError(response.message)
      }
    }

    //请求完成回调
    const completeCallback = config.complete || function () {
      if(config.loading !== false){
        globalVal.hideLoading();
      }
    }


    // 使用缓存数据
    if (config.method === METHOD_GET) {

      const lastResponse = AjaxCache.get(config.url)
      if (config.useLast && lastResponse) {
        successCallback(lastResponse)
      }
    }

    config.success = function (response:any) {
      const statusCode = response.status;
      const data = response.data;

      if (statusCode == 200) {

        successCallback(data);
        //设置缓存数据
        if (config.useLast) {
          AjaxCache.set(config.url, response);
        }
      }
      else {
        if (statusCode == 401){
          //TokenManager.clear();
        }
        if ((statusCode == 401) && !config.anonymous) {
          config.commonReject && config.commonReject(data)
          globalVal.login();
        }
        else {
          if(data && !data.message){
            data.message = data.msg;
          }
          if (data && data.message){
            config.commonReject && config.commonReject(data)
            errorCallback(data, statusCode, response.header)
          }
          else if(!config.anonymous){
            showError('请求失败');

          }
        }

      }
    }

    config.fail = config.fail || function (response:any) {
      const statusCode = response ? response.status : null;
      const data = response ? response.data : null;

      if ((statusCode == 401) && !config.anonymous) {
        config.commonReject && config.commonReject(data)
        globalVal.login();
      }
      else {
        if(data && !data.message){
          data.message = data.msg;
        }
        if (data && data.message){
          config.commonReject && config.commonReject(data)
          errorCallback(data, statusCode, response.header)
        }
        else if(!config.anonymous){
          showError('请求失败，请检查网络')

        }
      }


    }

    config.complete = function(res:any){
      delete lockMap[lockKey]
      completeCallback(res);
    }

    if (config.url.indexOf('http') !== 0) {
      config.url = config.baseURL + config.url;
    }


    // if (config.loading !== false) {
    //   var text = config.loadingText|| '';
    //   global.showLoading(text);
    // }

    axios(config).then(function (result:any) {
      setTimeout(() => {
        config.complete();
      }, 1)
      config.success(result);

    }).catch(function (error:any) {
      setTimeout(() => {
        config.complete();
      }, 1)
      config.fail(error.response)

    })
  },
  /**
   * 设置Authorization
   * @param {Object} config
   */
  setAuthorization:function(config:any):void{
	// 配置 DEBUG userId 方便调试
	if(globalVal.DEBUG_USERID){
	    config.headers['Authorization'] = "DEBUG userId=" + globalVal.DEBUG_USERID;
	}
	else{
	   // 设置授权头部
	   const token = TokenManager.get();
	   config.headers['Authorization'] = generateAuthorization(config.method, config.baseURL + decodeURIComponent(config.url), token)
	}
  },
  /**
   * 获取授权信息
   * @param config
   */
  getAuthorization: function (config:any) {
    config.method = (config.method || config.type || METHOD_GET).toUpperCase()
    Http.combine(config)

	// 配置 DEBUG userId 方便调试
	if(globalVal.DEBUG_USERID){
	    return "DEBUG userId=" + globalVal.DEBUG_USERID;
	}
	else{
	   // 设置授权头部
	   const token = TokenManager.get();
	   return generateAuthorization(config.method, config.baseURL + decodeURIComponent(config.url), token)
	}
  },
  /**
   * 数据合并
   * @param config
   */
  combine: function (config:any) {
    // 替换路径占位符号
    if (config.path) {
		for (const key in config.path) {
			config.url = config.url.replace('{' + key + '}', config.path[key])
		}
		delete config.path
    }
    config.data = config.data || config.body || config.form;


    const isFormData = config.isFormData
    if (!isFormData) {
      // 过滤掉null数据
      let data = config.data;
      let method = config.method
      if(config.query){
        data = config.query
        method = METHOD_GET
      }
      config.data = Http.filter(config.data)
      data = Http.filter(data)
      config.url = httpUrlFormat(config.url, data, method)
    }
    // 非http开头的加上API_BASE_PATH
    if (config.url.indexOf('http') !== 0) {
      if (!globalVal.API_BASE_PATH) {
        throw new Error('请配置接口基本地址global.API_BASE_PATH')
      }
      config.baseURL = globalVal.API_BASE_PATH
    }
    delete config.body
    delete config.query
    delete config.form
  },
  filter: function (data:any) {
    if (Object.prototype.toString.call(data) === '[object Array]') {
      for(let i=0 ; i<data.length; i++){
        data[i] = Http.filter(data[i]);
      }
      return data;
    }

    const _data:any = {}
    for (const i in data) {
      let val = data[i]
      if (val === null || typeof val === 'undefined') {
        continue
      }
      if (/\d{4}-\d{1,2}-\d{1,2} {1}\d{1,2}:\d{1,2}:\d{1,2}$/.test(val)) {
        val = DateUtil.toDate(val)
      }
      _data[i] = val
    }
    return _data
  }
}
export default Http
